package com.marketing.tenant.util;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * JWT工具类 - 租户服务专用
 * 主要用于解析和验证token，不负责生成token
 */
@Component
public class JwtUtil {

    private static final Logger logger = LoggerFactory.getLogger(JwtUtil.class);

    @Value("${jwt.secret:marketing-system-jwt-secret-key-2025-this-is-a-very-long-secret-key-for-hs512-algorithm-security}")
    private String jwtSecret;

    /**
     * 从Token中获取用户名
     */
    public String getUsernameFromToken(String token) {
        logger.debug("从Token中获取用户名");
        
        try {
            Claims claims = getClaimsFromToken(token);
            String username = claims.getSubject();
            logger.debug("从Token获取用户名成功: {}", username);
            return username;
        } catch (Exception e) {
            logger.warn("从Token获取用户名失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 从Token中获取用户ID
     */
    public Long getUserIdFromToken(String token) {
        logger.debug("从Token中获取用户ID");
        
        try {
            Claims claims = getClaimsFromToken(token);
            Long userId = claims.get("userId", Long.class);
            logger.debug("从Token获取用户ID成功: {}", userId);
            return userId;
        } catch (Exception e) {
            logger.warn("从Token获取用户ID失败: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 从Token中获取主要角色
     */
    public String getRoleFromToken(String token) {
        logger.debug("从Token中获取主要角色");
        
        try {
            Claims claims = getClaimsFromToken(token);
            String role = claims.get("role", String.class);
            logger.debug("从Token获取主要角色成功: {}", role);
            return role;
        } catch (Exception e) {
            logger.warn("从Token获取主要角色失败: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 从Token中获取所有角色编码
     */
    @SuppressWarnings("unchecked")
    public List<String> getRoleCodesFromToken(String token) {
        logger.debug("从Token中获取所有角色编码");
        
        try {
            Claims claims = getClaimsFromToken(token);
            List<String> roleCodes = (List<String>) claims.get("roles");
            logger.debug("从Token获取角色编码成功，数量: {}", roleCodes != null ? roleCodes.size() : 0);
            return roleCodes;
        } catch (Exception e) {
            logger.warn("从Token获取角色编码失败: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 从Token中获取所有权限编码
     */
    @SuppressWarnings("unchecked")
    public Set<String> getPermissionCodesFromToken(String token) {
        logger.debug("从Token中获取所有权限编码");
        
        try {
            Claims claims = getClaimsFromToken(token);
            List<String> permissionList = (List<String>) claims.get("permissions");
            if (permissionList != null) {
                Set<String> permissionCodes = Set.copyOf(permissionList);
                logger.debug("从Token获取权限编码成功，数量: {}", permissionCodes.size());
                return permissionCodes;
            }
            return null;
        } catch (Exception e) {
            logger.warn("从Token获取权限编码失败: {}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 检查Token中是否包含指定权限
     */
    public boolean hasPermission(String token, String permissionCode) {
        logger.debug("检查Token中是否包含权限: {}", permissionCode);
        
        try {
            Set<String> permissions = getPermissionCodesFromToken(token);
            boolean hasPermission = permissions != null && permissions.contains(permissionCode);
            logger.debug("权限检查结果，权限: {}, 拥有: {}", permissionCode, hasPermission);
            return hasPermission;
        } catch (Exception e) {
            logger.warn("权限检查失败，权限: {}, 异常: {}", permissionCode, e.getMessage());
            return false;
        }
    }
    
    /**
     * 检查Token中是否包含指定角色
     */
    public boolean hasRole(String token, String roleCode) {
        logger.debug("检查Token中是否包含角色: {}", roleCode);
        
        try {
            // 检查主要角色
            String mainRole = getRoleFromToken(token);
            if (roleCode.equals(mainRole)) {
                logger.debug("在主要角色中找到匹配，角色: {}", roleCode);
                return true;
            }
            
            // 检查所有角色列表
            List<String> roles = getRoleCodesFromToken(token);
            boolean hasRole = roles != null && roles.contains(roleCode);
            logger.debug("角色检查结果，角色: {}, 拥有: {}", roleCode, hasRole);
            return hasRole;
        } catch (Exception e) {
            logger.warn("角色检查失败，角色: {}, 异常: {}", roleCode, e.getMessage());
            return false;
        }
    }

    /**
     * 从Token中获取过期时间
     */
    public Date getExpirationDateFromToken(String token) {
        try {
            Claims claims = getClaimsFromToken(token);
            return claims.getExpiration();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 验证Token是否有效
     */
    public Boolean validateToken(String token) {
        logger.debug("验证Token有效性");
        
        try {
            Claims claims = getClaimsFromToken(token);
            String username = claims.getSubject();
            boolean isValid = !isTokenExpired(token);
            
            if (isValid) {
                logger.debug("Token验证成功，用户名: {}", username);
            } else {
                logger.warn("Token验证失败，用户名: {}, Token已过期", username);
            }
            
            return isValid;
        } catch (Exception e) {
            logger.error("Token验证过程中发生异常: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 检查Token是否过期
     */
    public Boolean isTokenExpired(String token) {
        logger.debug("检查Token是否过期");
        
        try {
            final Date expiration = getExpirationDateFromToken(token);
            Date now = new Date();
            boolean expired = expiration.before(now);
            
            if (expired) {
                logger.debug("Token已过期，过期时间: {}, 当前时间: {}", expiration, now);
            } else {
                logger.debug("Token未过期，过期时间: {}, 当前时间: {}", expiration, now);
            }
            
            return expired;
        } catch (Exception e) {
            logger.warn("Token过期检查失败，默认为已过期: {}", e.getMessage());
            return true;
        }
    }

    /**
     * 从Token中获取Claims
     */
    private Claims getClaimsFromToken(String token) {
        logger.debug("从Token中解析Claims");
        
        try {
            Claims claims = Jwts.parserBuilder()
                    .setSigningKey(getSigningKey())
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
                    
            logger.debug("Token Claims解析成功，subject: {}, 过期时间: {}", claims.getSubject(), claims.getExpiration());
            return claims;
        } catch (ExpiredJwtException e) {
            logger.warn("Token已过期: {}", e.getMessage());
            throw e;
        } catch (MalformedJwtException e) {
            logger.warn("Token格式错误: {}", e.getMessage());
            throw e;
        } catch (SignatureException e) {
            logger.warn("Token签名验证失败: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            logger.error("Token解析失败: {}", e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 获取签名密钥
     */
    private SecretKey getSigningKey() {
        byte[] keyBytes = jwtSecret.getBytes();
        return Keys.hmacShaKeyFor(keyBytes);
    }
}